/**
 * 
 */
package com.quiz.activity.questions;

import java.util.Arrays;
import java.util.Collections;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.flurry.android.FlurryAgent;
import com.quiz.activity.R;
import com.quiz.activity.util.QuizUtil;
import com.quiz.dao.PlayerDatasource;
import com.quiz.dao.QuestionDataSource;
import com.quiz.dao.SectionDataSource;
import com.quiz.model.Player;
import com.quiz.model.Question;
import com.quiz.model.Section;


/**
 *
 * @author Brian Boyle
 * Apr 11, 2012
 */
public class QuestionActivity extends Activity implements OnClickListener {

    private QuestionDataSource questionDatasource;
    private PlayerDatasource playerDataSource;
    private SectionDataSource sectionDataSource;
    private int questionCount;
    private Question question;
    private Player player;
    private Section section;
    private CountDownTimer countdownTimer;
    private SharedPreferences sharedPrefs;

    //Answer variables
    private boolean hasAttemptedAnAnswer;
    private int speedBonusScore;
    private int correctQuestionCount;


    public static final int CORRECT_ANSWER_DIALOG = 1;
    public static final int WHACKED_DIALOG = 2;
    public static final int OUT_TIME_DIALOG = 3;
    public static final String LIVES_LEFT = "LIVES_LEFT";
    public static final String CURRENT_SCORE = "CURRENT_SCORE";
    public static final String PREF_FILE = "QUESTION_DATA";


    /**
     * {@inheritDoc}
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        FlurryAgent.onStartSession(this, QuizUtil.FLURRY_KEY);

        setContentView(R.layout.question);

        playerDataSource = new PlayerDatasource(this);
        questionDatasource = new QuestionDataSource(this);
        sectionDataSource = new SectionDataSource(this);

        Bundle bundle = getIntent().getExtras();
        questionCount = bundle.getInt("questionCount");
        correctQuestionCount = bundle.getInt("correctQuestionCount");
        this.section = sectionDataSource.getSectionById(bundle.getLong("sectionId"));
        //Retrieve a random question for this section
        question = questionDatasource.getRandomQuestion(this.section.getId());

        setupNumerOfLives();

        TextView logo = (TextView) findViewById(R.id.logoText);
        QuizUtil.setMafiaFont(logo, 48, getAssets());

        TextView questionView = (TextView) findViewById(R.id.questionTextView);
        if (question.getQuestion().length() > 100) {
            questionView.setTextSize(14);
        }
        questionView.setText(question.getQuestion());

        TextView statusView = (TextView) findViewById(R.id.statusText);
        statusView.setText("Question " + questionCount + "/" + section.getNumberOfQuestions());

        buildAnswerList(question);
        updateBottomBarView(false);
        sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);

    }

    private void setupNumerOfLives() {
        SharedPreferences settings = getSharedPreferences(QuestionActivity.PREF_FILE, MODE_PRIVATE);
        if (settings.getInt(LIVES_LEFT, 0) == 0) {
            player = playerDataSource.getPlayerDetails();
            SharedPreferences.Editor editor = settings.edit();
            editor.putInt(LIVES_LEFT, player.getLives());
            editor.commit();
        }

    }

    private void clearStoredValues() {
        SharedPreferences settings = getSharedPreferences(QuestionActivity.PREF_FILE, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.clear();
        editor.commit();
    }

    private int getNumberOfLives() {
        SharedPreferences settings = getSharedPreferences(QuestionActivity.PREF_FILE, MODE_PRIVATE);
        return settings.getInt(LIVES_LEFT, 0);
    }


    private void loseALife() {
        SharedPreferences settings = getSharedPreferences(QuestionActivity.PREF_FILE, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(LIVES_LEFT, getNumberOfLives() - 1);
        editor.commit();
        //Udpate the lives view
        updateBottomBarView(true);
    }

    private int getCurrentScore() {
        SharedPreferences settings = getSharedPreferences(QuestionActivity.PREF_FILE, MODE_PRIVATE);
        return settings.getInt(CURRENT_SCORE, 0);
    }

    private void addToScore(int score) {
        SharedPreferences settings = getSharedPreferences(QuestionActivity.PREF_FILE, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(CURRENT_SCORE, getCurrentScore() + score);
        editor.commit();
    }

    /**
     * When the user selects an answer, check if its correct.
     * {@inheritDoc}
     */
    public void onClick(View view) {
        checkAnswer((Button) view);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////Handle Answers//////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * @param button
     */
    private void checkAnswer(Button button) {
        if (button.getText().equals(question.getAnswer())) {
            handleCorrectAnswer();
        } else {
            incorrectAnswerSelected(button);
        }
    }

    /**
     * 
     */
    private void handleCorrectAnswer() {
        //increment the number of correct questions count
        this.correctQuestionCount++;
        addToScore(this.section.getPointsPerQuestion());
        //Calculate first guess bonus
        calculateFirstGuessBonus();
        //Calculate speed bonus
        calculateSpeedBonus();
        showDialog(CORRECT_ANSWER_DIALOG);
        this.countdownTimer.cancel();
        this.questionDatasource.updateQuestionToAsked(this.question.getId());
    }

    /**
     * 
     */
    private void calculateSpeedBonus() {
        TextView timerView = (TextView) findViewById(R.id.timer);
        int timeLeft = Integer.valueOf(timerView.getText().toString()).intValue();

        int bonusTimeLeft = this.section.getTimeAllowed() - 10;
        if (timeLeft > bonusTimeLeft) {
            speedBonusScore = (timeLeft - bonusTimeLeft) * this.section.getSpeedBonus();
            addToScore(speedBonusScore);
        }

    }

    private void calculateFirstGuessBonus() {
        if (!hasAttemptedAnAnswer) {
            addToScore(this.section.getFirstGuessBonusPoint());
        }
    }

    MediaPlayer mp;

    /**
     * 
     */
    private void incorrectAnswerSelected(Button button) {
        if (sharedPrefs.getBoolean("sound_effects", false)) {
            mp = MediaPlayer.create(this, R.raw.shotgun);
            mp.start();
            mp.setOnCompletionListener(new OnCompletionListener() {

                public void onCompletion(MediaPlayer mp) {
                    mp.release();
                }
            });
        }
        TranslateAnimation moveLefttoRight = new TranslateAnimation(0, 700, 0, 0);
        moveLefttoRight.setDuration(300);
        moveLefttoRight.setFillAfter(true);
        button.startAnimation(moveLefttoRight);
        button.setEnabled(false);

        if (sharedPrefs.getBoolean("vibrations", false)) {
            Vibrator v = (Vibrator) getSystemService(QuestionActivity.VIBRATOR_SERVICE);
            v.vibrate(300);
        }
        loseALife();
        hasAttemptedAnAnswer = true;

        if (getNumberOfLives() == 0) {
            handleGettingWhacked();
        }
    }

    private void handleOutOfTime() {
        loseALife();
        if (getNumberOfLives() == 0) {
            handleGettingWhacked();
        } else {
            Vibrator v = (Vibrator) getSystemService(QuestionActivity.VIBRATOR_SERVICE);
            v.vibrate(300);
            showDialog(OUT_TIME_DIALOG);
        }
    }

    /**
     * 
     */
    private void handleGettingWhacked() {
        showDialog(WHACKED_DIALOG);
        this.countdownTimer.cancel();
        if (player == null) {
            player = new Player();
            player.setLives(0);
            player.setStatus(Player.STATUS_DEAD);
            clearStoredValues();
        }
        playerDataSource.updatePlayerLivesAndStatus(player);
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////Alert Dialogs//////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * {@inheritDoc}
     */
    @Override
    protected Dialog onCreateDialog(int id) {
        Dialog dialog = null;
        switch (id) {
            case CORRECT_ANSWER_DIALOG:
                dialog = buildCorrectAnswerDialog(dialog);
                break;
            case WHACKED_DIALOG:
                dialog = buildDialog("You just got whacked", "Oooooh!", new WhackedDialogClickListener(this));
                break;
            case OUT_TIME_DIALOG:
                OnClickListener clickListener;
                String buttonText;
                if (this.questionCount == this.section.getNumberOfQuestions()) {
                    buttonText = "Ok";
                    clickListener = new QuestionsFinishedClickListener(this, this.section, this.correctQuestionCount, getCurrentScore());
                } else {
                    buttonText = "Next Question";
                    clickListener = new NextQuestionClickListener(this, this.questionCount + 1, this.section.getId(), QuestionActivity.OUT_TIME_DIALOG, this.correctQuestionCount);
                }
                dialog = buildDialog("Times up !", buttonText, clickListener);
                break;
            default:
                dialog = null;
        }
        return dialog;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        super.onPrepareDialog(id, dialog);
        dialog = null;
    }

    /**
     * @return
     */
    private Dialog buildCorrectAnswerDialog(Dialog dialog) {
        AlertDialog.Builder builder = new Builder(this);
        LayoutInflater inflater = getLayoutInflater();
        LinearLayout dialogView = (LinearLayout) inflater.inflate(R.layout.correct_answer_dialog, (ViewGroup) findViewById(R.id.linear_layout_answer));

        addCorrectAnswerPointsToDialog(dialogView);
        int position = 1;
        position = addFirstGuessBonusToDialog(dialogView, position);
        addSpeedBonusToDialog(dialogView, position);

        Button nextQuestionButton = (Button) dialogView.findViewById(R.id.nextQuestionButton);
        nextQuestionButton.setBackgroundResource(R.drawable.red_button);
        nextQuestionButton.setTextColor(Color.WHITE);
        nextQuestionButton.setTypeface(null, Typeface.BOLD);

        OnClickListener clickListener;
        if (this.questionCount == this.section.getNumberOfQuestions()) {
            nextQuestionButton.setText("Ok");
            clickListener = new QuestionsFinishedClickListener(this, this.section, this.correctQuestionCount, getCurrentScore());
        } else {
            clickListener = new NextQuestionClickListener(this, this.questionCount + 1, this.section.getId(), QuestionActivity.CORRECT_ANSWER_DIALOG, this.correctQuestionCount);
        }
        nextQuestionButton.setOnClickListener(clickListener);

        TextView correctAnswerText = (TextView) dialogView.findViewById(R.id.correctText);
        QuizUtil.setMafiaFont(correctAnswerText, 32, getAssets());

        builder.setView(dialogView);
        dialog = builder.create();
        //Prevent the user from dismissing the dialog with the back button
        dialog.setCancelable(false);
        return dialog;
    }

    private void addCorrectAnswerPointsToDialog(LinearLayout dialogView) {
        TextView pointsText = new TextView(this);
        pointsText.setText("+ " + this.section.getPointsPerQuestion() + " points");
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(60, 0, 0, 0);
        dialogView.addView(pointsText, 1, layoutParams);
    }

    /**
     * @param dialogView
     */
    private int addFirstGuessBonusToDialog(LinearLayout dialogView, int position) {
        if (!hasAttemptedAnAnswer) {
            position++;
            TextView pointsText = new TextView(this);
            pointsText.setText("+ " + this.section.getFirstGuessBonusPoint() + " First Guess Bonus");
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.setMargins(60, 0, 0, 0);
            dialogView.addView(pointsText, position, layoutParams);
        }
        return position;
    }

    /**
     * @param dialogView
     */
    private void addSpeedBonusToDialog(LinearLayout dialogView, int position) {

        if (this.speedBonusScore != 0) {

            TextView pointsText = new TextView(this);
            pointsText.setText("+ " + this.speedBonusScore + " Speed Bonus");
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.setMargins(60, 0, 0, 0);
            dialogView.addView(pointsText, position, layoutParams);
        }
    }

    /**
     * 
     * @param dialog
     * @return
     */
    private Dialog buildDialog(String title, String buttonText, OnClickListener nextStepListener) {
        AlertDialog.Builder builder = new Builder(this);
        LayoutInflater inflater = getLayoutInflater();
        LinearLayout dialogView = (LinearLayout) inflater.inflate(R.layout.correct_answer_dialog, (ViewGroup) findViewById(R.id.linear_layout_answer));

        Button nextQuestionButton = (Button) dialogView.findViewById(R.id.nextQuestionButton);
        nextQuestionButton.setOnClickListener(nextStepListener);
        nextQuestionButton.setText(buttonText);
        nextQuestionButton.setBackgroundResource(R.drawable.red_button);
        nextQuestionButton.setTextColor(Color.WHITE);
        nextQuestionButton.setTypeface(null, Typeface.BOLD);

        TextView correctAnswerText = (TextView) dialogView.findViewById(R.id.correctText);
        correctAnswerText.setText(title);
        QuizUtil.setMafiaFont(correctAnswerText, 32, getAssets());

        builder.setView(dialogView);
        Dialog dialog = builder.create();
        //Prevent the user from dismissing the dialog with the back button
        dialog.setCancelable(false);
        return dialog;
    }


    private void updateBottomBarView(boolean removeViews) {

        LinearLayout bottomBar = (LinearLayout) findViewById(R.id.bottomBar);
        //Remove the existing image views for the lives and replace them with the new lives.
        if (removeViews) {
            bottomBar.removeViews(2, 3);
        }
        QuizUtil.buildScoreAndLivesBottomBar(getCurrentScore(), getNumberOfLives(), bottomBar, this);
    }


    /**
     * Show the countdown timer on screen and update the time every 1 second;
     */
    private void displayTimer() {

        final TextView timerView = (TextView) findViewById(R.id.timer);
        QuizUtil.setMafiaFont(timerView, 64, getAssets());

        int timeAllowed = (this.section.getTimeAllowed() + 1) * 1000;
        countdownTimer = new CountDownTimer(timeAllowed, 1000) {

            @Override
            public void onTick(long millisUntilFinished) {
                timerView.setText("" + millisUntilFinished / 1000);
            }

            @Override
            public void onFinish() {
                timerView.setText("" + 0);
                handleOutOfTime();
            }

        }.start();
    }


    /**
     * @param question
     */
    private void buildAnswerList(Question question) {
        String[] answers = new String[] { question.getAnswer(), question.getPossible1(), question.getPossible2(), question.getPossible3() };
        Collections.shuffle(Arrays.asList(answers));

        Button answerButton1 = (Button) findViewById(R.id.answerButton1);
        answerButton1.setText(answers[0]);
        if (answerButton1.getText().length() > 60) {
            answerButton1.setTextSize(12);
        }
        answerButton1.setOnClickListener(this);

        Button answerButton2 = (Button) findViewById(R.id.answerButton2);
        answerButton2.setText(answers[1]);
        if (answerButton2.getText().length() > 60) {
            answerButton2.setTextSize(12);
        }
        answerButton2.setOnClickListener(this);

        Button answerButton3 = (Button) findViewById(R.id.answerButton3);
        answerButton3.setText(answers[2]);
        if (answerButton3.getText().length() > 60) {
            answerButton3.setTextSize(12);
        }
        answerButton3.setOnClickListener(this);

        Button answerButton4 = (Button) findViewById(R.id.answerButton4);
        answerButton4.setText(answers[3]);
        if (answerButton4.getText().length() > 60) {
            answerButton4.setTextSize(12);
        }
        answerButton4.setOnClickListener(this);
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected void onPause() {
        super.onPause();
        questionDatasource.close();
        playerDataSource.close();
        sectionDataSource.close();
        this.countdownTimer.cancel();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onResume() {
        super.onResume();
        questionDatasource.open();
        playerDataSource.open();
        sectionDataSource.open();
        displayTimer();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onBackPressed() {
        clearStoredValues();
        super.onBackPressed();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onStop() {
        super.onStop();
        FlurryAgent.onEndSession(this);
    }

}
